#pragma once
#include "../common/consumer.hpp"
#include "../common/mq_msg/mq_msg.pb.h"
#include "../common/helper.hpp"
#include "../common/log.hpp"
#include <iostream>
#include <functional>
#include <mutex>
#include <memory>

namespace xzt
{
    // 以队列为单元管理消费者
    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;

        QueueConsumer(const std::string &queue_name)
            : _queue_name(queue_name), _rotate_num(0) {}

        ~QueueConsumer() = default;

    public:
        // 注册消费者
        Consumer::ptr create(const std::string &tag, const std::string &queue_name,
                             bool auto_ack, const ConsumerCallback &cb)
        {
            // 队列中指定消费者是否存在 (此处放在lock外面, 避免死锁)
            if (exist(tag))
            {
                return Consumer::ptr();
            }

            std::lock_guard<std::mutex> lock(_mutex);
            // 注册消费者
            auto consumer = std::make_shared<Consumer>(tag, queue_name, auto_ack, cb);
            _consumers.push_back(consumer);
            return consumer;
        }

        // 注销消费者
        void remove(const std::string &tag)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it)
            {
                if ((*it)->_tag == tag)
                {
                    _consumers.erase(it);
                    break;
                }
            }
        }

        // 队列轮转获取消费者
        Consumer::ptr choose()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_consumers.empty())
            {
                return Consumer::ptr();
            }
            // 轮转获取消费者
            _rotate_num = _rotate_num % _consumers.size();
            return _consumers[_rotate_num++];
        }

        // 队列中的消费者是否为空
        bool empty()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            return _consumers.empty();
        }

        // 队列中指定消费者是否存在
        bool exist(const std::string &tag)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            for (auto &consumer : _consumers)
            {
                if (consumer->_tag == tag)
                {
                    return true;
                }
            }
            return false;
        }

        // 清空队列消费者
        void clear()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _consumers.clear();
        }

    private:
        std::mutex _mutex;                     // 队列消费者管理器的互斥锁
        std::string _queue_name;               // 队列名称
        uint64_t _rotate_num;                  // 队列轮转编号
        std::vector<Consumer::ptr> _consumers; // 队列消费者列表
    };

    class ConsumerManager
    {
    public:
        using ptr = std::shared_ptr<ConsumerManager>;

        ConsumerManager() = default;

        ~ConsumerManager() = default;

    public:
        // 对队列的管理
        void declareQueueConsumer(const std::string &queue_name)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_queues.find(queue_name) != _queues.end())
            {
                return;
            }
            _queues.insert(std::make_pair(queue_name, std::make_shared<QueueConsumer>(queue_name)));
        }
        void removeQueueConsumer(const std::string &queue_name)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_queues.find(queue_name) == _queues.end())
            {
                return;
            }
            _queues.erase(queue_name);
        }

        // 注册消费者
        Consumer::ptr create(const std::string &tag, const std::string &queue_name,
                             bool auto_ack, const ConsumerCallback &cb)
        {
            QueueConsumer::ptr p_qc;
            {
                std::lock_guard<std::mutex> lock(_mutex);
                // 队列中指定消费者是否存在
                if (_queues.find(queue_name) == _queues.end())
                {
                    ELOG("ConsumerManager::create -> 没有找到对应的消费者队列管理句柄：%s", queue_name.c_str());
                    return Consumer::ptr();
                }
                p_qc = _queues[queue_name];
            }
            return p_qc->create(tag, queue_name, auto_ack, cb);
        }

        // 注销消费者
        void remove(const std::string &tag, const std::string &queue_name)
        {
            QueueConsumer::ptr p_qc;
            {
                std::lock_guard<std::mutex> lock(_mutex);
                // 队列中指定消费者是否存在
                if (_queues.find(queue_name) == _queues.end())
                {
                    ELOG("ConsumerManager::remove -> 没有找到对应的消费者队列管理句柄：%s", queue_name.c_str());
                    return;
                }
                p_qc = _queues[queue_name];
            }

            p_qc->remove(tag);
        }

        // 队列轮转获取消费者
        Consumer::ptr choose(const std::string &queue_name)
        {
            QueueConsumer::ptr p_qc;
            {
                std::lock_guard<std::mutex> lock(_mutex);
                // 队列中指定消费者是否存在
                if (_queues.find(queue_name) == _queues.end())
                {
                    ELOG("ConsumerManager::choose -> 没有找到对应的消费者队列管理句柄：%s", queue_name.c_str());
                    return Consumer::ptr();
                }
                p_qc = _queues[queue_name];
            }

            return p_qc->choose();
        }

        // 队列中的消费者是否为空
        bool empty(const std::string &queue_name)
        {
            QueueConsumer::ptr p_qc;
            {
                std::lock_guard<std::mutex> lock(_mutex);
                // 队列中指定消费者是否存在
                if (_queues.find(queue_name) == _queues.end())
                {
                    ELOG("ConsumerManager::empty -> 没有找到对应的消费者队列管理句柄：%s", queue_name.c_str());
                    return true;
                }
                p_qc = _queues[queue_name];
            }

            return p_qc->empty();
        }

        // 队列中指定消费者是否存在
        bool exist(const std::string &tag, const std::string &queue_name)
        {
            QueueConsumer::ptr p_qc;
            {
                std::lock_guard<std::mutex> lock(_mutex);
                // 队列中指定消费者是否存在
                if (_queues.find(queue_name) == _queues.end())
                {
                    ELOG("ConsumerManager::create -> 没有找到对应的消费者队列管理句柄：%s", queue_name.c_str());
                    return false;
                }
                p_qc = _queues[queue_name];
            }

            return p_qc->exist(tag);
        }

        // 清空所有队列消费者
        void clear()
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _queues.clear();
        }

    private:
        std::mutex _mutex;                                           // 消费者管理器的互斥锁
        std::unordered_map<std::string, QueueConsumer::ptr> _queues; // 队列消费者管理器
    };
}
